Insecure Bank2 취약점(3)

Insecure Bank2 취약점(3)

Description
로컬 암호화 이슈
category
MobileHacking
Tag
Mobile Security
Andorid
Date
Jan 18, 2024 07:48 AM

로컬 암호화 이슈

취약점 소개

해당 취약점은 중요 정보 암호화가 로컬에서 이루어지는데 해당 부분의 소스코드가 평문으로 표기되어 중요정보를 암호화, 복호화 할 수 있는 취약점이다.
 
InsecureBankv2는 Autofill Credentials라는 기능을 하는 버튼이 있는데 해당 버튼의 기능은 가장 최근에 로그인한 인증 정보를 불러와주는 기능이다.
notion image
 
로그인 시 해당 정보를 저장하기 때문에 DoLogin.class를 살펴보면 로그인 성공 시 saveCreds 함수에 로그인 정보를 담고 호출하는 것을 볼 수 있다.
if (DoLogin.this.result != null) { if (DoLogin.this.result.indexOf("Correct Credentials") != -1) { Log.d("Successful Login:", ", account=" + DoLogin.this.username + ":" + DoLogin.this.password); saveCreds(DoLogin.this.username, DoLogin.this.password); trackUserLogins(); Intent pL = new Intent(DoLogin.this.getApplicationContext(), PostLogin.class); pL.putExtra("uname", DoLogin.this.username); DoLogin.this.startActivity(pL); return; } Intent xi = new Intent(DoLogin.this.getApplicationContext(), WrongLogin.class); DoLogin.this.startActivity(xi); }
saveCreds를 호출하는 부분
 
saveCreds의 메서드를 확인해 보면 SharedPreferences API를 사용하여 “mySharedPreferences”란 파일에 username은 base64로 인코딩하고, password는 CryptoClass의 aesEncryptedString를 이용하여 암호화 한 뒤 저장하는 것을 볼 수 있다.
private void saveCreds(String username, String password) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException { SharedPreferences mySharedPreferences = DoLogin.this.getSharedPreferences("mySharedPreferences", 0); SharedPreferences.Editor editor = mySharedPreferences.edit(); DoLogin.this.rememberme_username = username; DoLogin.this.rememberme_password = password; String base64Username = new String(Base64.encodeToString(DoLogin.this.rememberme_username.getBytes(), 4)); CryptoClass crypt = new CryptoClass(); DoLogin.this.superSecurePassword = crypt.aesEncryptedString(DoLogin.this.rememberme_password); editor.putString("EncryptedUsername", base64Username); editor.putString("superSecurePassword", DoLogin.this.superSecurePassword); editor.commit(); }
saveCreds 메서드
 
SharedPreferences API를 사용하여 정보를 저장하게되면 /data/data/com.test.test/shared_prefs 위치에 저장이 된다. 따라서 ADB를 이용하여 해당 위치의 mySharedPreferences.xml를 확인해보면 암호화 된 usersename과 password가 있는 것을 볼 수 있다.
notion image
 
Encryptedusername 값을 Base64로 디코딩 하면 다음과 같이 값이 나온다.
디코딩 도구는 Dreamhack Tool을 이용하였다.
notion image
 
superSecurePassword 값은 CryptoClass의 aesEncryptedString로 암호화 되었기 때문에 CrptoClass.class를 분석해 보았다.
aesEncryptedString는 string을 입력 받아 aes256encrypt를 이용하여 키 "This is the super secret key 123" 와 함께 암호화 하는 것을 볼 수 있다.
public class CryptoClass { String base64Text; byte[] cipherData; String cipherText; String plainText; String key = "This is the super secret key 123"; byte[] ivBytes = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; public static byte[] aes256encrypt(byte[] ivBytes, byte[] keyBytes, byte[] textBytes) throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException { AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes); SecretKeySpec newKey = new SecretKeySpec(keyBytes, "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(1, newKey, ivSpec); return cipher.doFinal(textBytes); } public static byte[] aes256decrypt(byte[] ivBytes, byte[] keyBytes, byte[] textBytes) throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException { AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivBytes); SecretKeySpec newKey = new SecretKeySpec(keyBytes, "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(2, newKey, ivSpec); return cipher.doFinal(textBytes); } public String aesDeccryptedString(String theString) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException { byte[] keyBytes = this.key.getBytes("UTF-8"); this.cipherData = aes256decrypt(this.ivBytes, keyBytes, Base64.decode(theString.getBytes("UTF-8"), 0)); this.plainText = new String(this.cipherData, "UTF-8"); return this.plainText; } public String aesEncryptedString(String theString) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException { byte[] keyBytes = this.key.getBytes("UTF-8"); this.plainText = theString; this.cipherData = aes256encrypt(this.ivBytes, keyBytes, this.plainText.getBytes("UTF-8")); this.cipherText = Base64.encodeToString(this.cipherData, 0); return this.cipherText; } }
 
따라서 대칭키 암호화를 사용하고 소스코드가 난독화 되어있지 않아 키가 공개되어 있으므로 superSecurePassword 값을 간단히 복호화 시켜 얻을 수 있었다.
복호화 도구는 https://encode-decode.com/aes256-encrypt-online/를 사용하였다.
notion image
 

대응방안

username이 단순 base64로 인코딩 되어 저장되어 저장하기 때문에 암호화를 통해 저장한다.
소스코드가 난독화 되어있지 않아 중요 정보가 노출되니 소스코드 난독화를 진행하여야 한다.